#include "../corelib/timer_queue.hh"
#include "unittest/unittest.hh"
#include <chrono>

using namespace kratos::corelib;

FIXTURE_BEGIN(TimerQueue)

CASE(TestInvalidArgument) {
    TimerQueue queue;
    ASSERT_TRUE(INVALID_TIMER_ID == queue.startTimer(0, 1));
    ASSERT_TRUE(INVALID_TIMER_ID != queue.startTimer(1, 0));

    ASSERT_TRUE(INVALID_TIMER_ID == queue.startTimerOnce(0, 1));
    ASSERT_TRUE(INVALID_TIMER_ID != queue.startTimerOnce(1, 0));

    ASSERT_TRUE(!queue.cancel(INVALID_TIMER_ID));
}

CASE(TestStartStop) {
    TimerQueue queue;
    ASSERT_TRUE(queue.start());
    ASSERT_TRUE(!queue.start());

    ASSERT_TRUE(queue.stop());
    ASSERT_TRUE(!queue.stop());
}

CASE(TestStartTimer) {
    TimerQueue queue;
    queue.start();
    auto id = queue.startTimer(1000, 0);
    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
    ASSERT_TRUE(id == queue.checkExpired());
    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
    ASSERT_TRUE(id == queue.checkExpired());
}

CASE(TestCancel) {
    TimerQueue queue;
    queue.start();
    auto id = queue.startTimer(1000, 0);
    queue.cancel(id);
    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
    ASSERT_TRUE(INVALID_TIMER_ID == queue.checkExpired());
}

CASE(TestStartTimerOnce) {
    TimerQueue queue;
    queue.start();
    auto id = queue.startTimerOnce(1000, 0);
    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
    ASSERT_TRUE(id == queue.checkExpired());
    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
    ASSERT_TRUE(INVALID_TIMER_ID == queue.checkExpired());
}

CASE(TestStartTimerOnceAndCancel) {
    TimerQueue queue;
    queue.start();
    auto id = queue.startTimerOnce(1000, 0);
    queue.cancel(id);
    std::this_thread::sleep_for(std::chrono::milliseconds(1100));
    ASSERT_TRUE(INVALID_TIMER_ID == queue.checkExpired());
}

FIXTURE_END(TimerQueue)
